package cn.desk.commons.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.desk.commons.dao.IBaseDao;
import cn.desk.commons.entity.BaseEntity;
import cn.desk.commons.entity.LogicallyDelete;
import cn.desk.commons.entity.PageMode;
import cn.desk.commons.entity.Sequence;
import cn.desk.commons.exception.DeskException;
import cn.desk.commons.service.IBaseService;
import cn.desk.commons.util.ClassUtil;
import cn.desk.commons.util.QueryCondition;

public class BaseServiceImpl<T extends BaseEntity> implements IBaseService<T> {
	protected IBaseDao<T> baseDao;
	static final Logger logger = LoggerFactory.getLogger(BaseServiceImpl.class);

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * cn.desk.commons.service.IBaseService#list(cn.desk.commons.entity.BaseEntity
	 * )
	 */
	@Override
	public List<T> list(T t) {
		logger.debug("list start");
		try {
			return baseDao.list(t);
		} finally {
			logger.debug("list end");
		}
	}

	public IBaseDao<T> getBaseDao() {
		return baseDao;
	}

	public void setBaseDao(IBaseDao<T> baseDao) {
		this.baseDao = baseDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * cn.desk.commons.service.IBaseService#add(cn.desk.commons.entity.BaseEntity
	 * )
	 */
	@Override
	public void add(T t) {
		logger.debug("add start");
		T temp = baseDao.load(t.getClass(), t.getId());
		if (temp != null) {
			throw new DeskException("EM0001", t);
		}
		baseDao.insert(t);
		logger.debug("add end");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * cn.desk.commons.service.IBaseService#update(cn.desk.commons.entity.BaseEntity
	 * )
	 */
	@Override
	public void update(T t) {
		logger.debug("update start");
		verify(t);
		baseDao.modify(t);
		logger.debug("update end");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * cn.desk.commons.service.IBaseService#load(cn.desk.commons.entity.BaseEntity
	 * )
	 */
	@Override
	public T load(T t){
		logger.debug("load start");
		try {
			T temp = verify(t);
			return temp;
		} finally {
			logger.debug("load end");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * cn.desk.commons.service.IBaseService#delete(cn.desk.commons.entity.BaseEntity
	 * )
	 */
	@Override
	public void delete(T t) {
		logger.debug("delete start");
		T temp = verify(t);
		if(t instanceof LogicallyDelete){
			LogicallyDelete ld=(LogicallyDelete) temp;
			ld.setDeleteClass(LogicallyDelete.DELETECLASS_DELETED);
			baseDao.modify(temp);
		}else{
			baseDao.delete(temp);
		}
		logger.debug("delete end");
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * cn.desk.commons.service.IBaseService#update(cn.desk.commons.entity.BaseEntity
	 * )
	 */
	@Override
	public void merge(T t) {
		logger.debug("update start");
		verify(t);
		baseDao.merge(t);
		logger.debug("update end");
	}
	
	private T verify(T t) {
		T temp = baseDao.load(t.getClass(), t.getId());
		if (temp == null) {
			throw new DeskException("EM0002", t);
		}
		return temp;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * cn.desk.commons.service.IBaseService#listPage(cn.desk.commons.entity.
	 * PageMode, cn.desk.commons.entity.BaseEntity)
	 */
	@Override
	public PageMode<T> listPage(PageMode<T> page, T t) {
		logger.debug("listPage start");
		try {

			return listPage(page, t, null);
		} finally {
			logger.debug("listPage end");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * cn.desk.commons.service.IBaseService#listPage(cn.desk.commons.entity.
	 * PageMode, cn.desk.commons.entity.BaseEntity)
	 */
	@Override
	public PageMode<T> listPage(PageMode<T> page, T t, String desc) {
		logger.debug("listPage start");
		try {

			QueryCondition condition = new QueryCondition();
			buildBase(condition, t);
			if (desc != null) {
				condition.asc(desc);
			}

			return baseDao.listPage(page, t.getClass(), condition);
		} finally {
			logger.debug("listPage end");
		}
	}

	/**
	 * @param condition 查询条件
	 * @param t 查询的entity
	 */
	protected void buildBase(QueryCondition condition, T t) {
		if (t != null) {
			Class<?> clazz = t.getClass();
			Map<String, Object> map = new HashMap<String, Object>();
			ClassUtil.buildProperty(t, clazz, map);
			for (Entry<String, Object> ent : map.entrySet()) {
				if (ent.getValue() instanceof String) {
					condition.andLike(ent.getKey(),
							String.valueOf(ent.getValue()),
							QueryCondition.MATCH_TYPE_ANY);
				} else if(ent.getValue()!=null){
					condition.andEq(ent.getKey(), ent.getValue());
				}
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * cn.desk.commons.service.IBaseService#listInByProperty(java.lang.Class,
	 * java.lang.String, java.lang.String[])
	 */
	public List<T> listInByProperty(final Class<?> clazz,
			final String property, final String[] dependencies) {
		logger.debug("listInByProperty start");
		try {
			return baseDao.listInByProperty(clazz, property, dependencies);
		} finally {
			logger.debug("listInByProperty end");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cn.desk.commons.service.IBaseService#listByProperty(java.lang.Class,
	 * java.lang.String, java.lang.Object)
	 */
	public List<T> listByProperty(final Class<?> clazz, final String property,
			Object value) {
		logger.debug("listByProperty start");
		try {
			QueryCondition con=new QueryCondition();
			con.andEq(property, value);
			return baseDao.list(clazz,con);
		} finally {
			logger.debug("listByProperty end");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cn.desk.commons.service.IBaseService#getMax(java.lang.Class,
	 * java.lang.String)
	 */
	@Override
	public String getMax(Class<?> clazz, String property) {
		logger.debug("getMax start");
		try {
			logger.info("Class:" + clazz + ",property:" + property);
			return baseDao.getMax(clazz, property);
		} finally {
			logger.debug("getMax end");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cn.desk.commons.service.IBaseService#getMax(java.lang.Class,
	 * java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public Integer getNextId(Class<?> clazz) {
		logger.debug("getMax start");
		try {
			logger.info("Class:" + clazz );
			Sequence sequence= (Sequence) baseDao.load(Sequence.class, clazz.getName());
			if(sequence == null){
				sequence=new Sequence();
				sequence.setId(clazz.getName());
				sequence.setNext(0);
				baseDao.insert((T) sequence);
				return 0;
			}else{
				sequence.setNext(sequence.getNext()+1);
				baseDao.modify((T) sequence);
			}
			return sequence.getNext();
		} finally {
			logger.debug("getMax end");
		}
	}
}
